package com.example.webcrawler.service.mpl;

import com.example.webcrawler.model.ApiRequest;
import io.github.bonigarcia.wdm.WebDriverManager;
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.core.har.HarEntry;
import net.lightbody.bmp.proxy.CaptureType;
import net.lightbody.bmp.client.ClientUtil;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class BrowserMobProxyService {

    private static final Logger logger = LoggerFactory.getLogger(BrowserMobProxyService.class);

    private BrowserMobProxy proxy;
    private AtomicBoolean serviceAvailable = new AtomicBoolean(false);

    public enum BrowserType {
        CHROME, FIREFOX, EDGE
    }

    @PostConstruct
    public void init() {
        try {
            // 初始化BrowserMobProxy
            proxy = new BrowserMobProxyServer();
            proxy.start(0);
            proxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
            serviceAvailable.set(true);
            logger.info("BrowserMob Proxy服务启动成功，端口: {}", proxy.getPort());
        } catch (Exception e) {
            logger.error("BrowserMob Proxy服务启动失败", e);
            serviceAvailable.set(false);
        }
    }

    @PreDestroy
    public void destroy() {
        if (proxy != null) {
            proxy.stop();
            logger.info("BrowserMob Proxy服务已停止");
        }
    }

    /**
     * 检查服务是否可用
     */
    public boolean isServiceAvailable() {
        return serviceAvailable.get();
    }

    /**
     * 开始记录HAR
     */
    public void startHarCapture(String pageRef) {
        if (isServiceAvailable()) {
            proxy.newHar(pageRef);
            logger.info("开始捕获HAR数据，页面引用: {}", pageRef);
        }
    }

    /**
     * 停止记录并获取HAR数据
     */
    public Har endHarCapture() {
        if (isServiceAvailable()) {
            Har har = proxy.endHar();
            logger.info("结束HAR数据捕获");
            return har;
        }
        return null;
    }

    /**
     * 获取捕获的请求列表
     */
    public List<ApiRequest> getCapturedRequests() {
        List<ApiRequest> requests = new ArrayList<>();
        if (isServiceAvailable()) {
            Har har = proxy.getHar();
            if (har != null && har.getLog() != null) {
                for (HarEntry entry : har.getLog().getEntries()) {
                    ApiRequest request = new ApiRequest();
                    request.setUrl(entry.getRequest().getUrl());
                    request.setMethod(entry.getRequest().getMethod());
                    request.setStatus(entry.getResponse().getStatus());

                    // 设置请求头
                    entry.getRequest().getHeaders().forEach(header ->
                            request.addHeader(header.getName(), header.getValue()));

                    // 设置响应头
                    entry.getResponse().getHeaders().forEach(header ->
                            request.addResponseHeader(header.getName(), header.getValue()));

                    request.setSource("BrowserMobProxy");
                    requests.add(request);
                }
                logger.info("从BrowserMob Proxy获取到 {} 个请求", requests.size());
            }
        }
        return requests;
    }

    /**
     * 创建Selenium WebDriver并配置代理
     */
    public WebDriver createWebDriverWithProxy() {
        return createWebDriverWithProxy(BrowserType.CHROME);
    }

    /**
     * 创建Selenium WebDriver并配置代理
     */
    public WebDriver createWebDriverWithProxy(BrowserType browserType) {
        if (!isServiceAvailable()) {
            throw new IllegalStateException("BrowserMob Proxy服务不可用");
        }

        Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);

        switch (browserType) {
            case CHROME:
                return createChromeDriver(seleniumProxy);
            case FIREFOX:
                return createFirefoxDriver(seleniumProxy);
            case EDGE:
                return createEdgeDriver(seleniumProxy);
            default:
                logger.warn("不支持的浏览器类型: {}, 使用Chrome作为默认浏览器", browserType);
                return createChromeDriver(seleniumProxy);
        }
    }

    /**
     * 创建ChromeDriver并配置代理
     */
    private WebDriver createChromeDriver(Proxy seleniumProxy) {
        logger.info("配置ChromeDriver");

        // 设置ChromeDriver下载到项目根目录的drivers文件夹中
        String projectPath = System.getProperty("user.dir");
        String driverPath = Paths.get(projectPath, "drivers").toString();

        WebDriverManager.chromedriver()
                .cachePath(driverPath)
                .setup();

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--ignore-certificate-errors");
        options.addArguments("--ignore-ssl-errors");
        options.addArguments("--headless");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-dev-shm-usage");
        options.addArguments("--disable-gpu");
        options.addArguments("--window-size=1920,1080");
        options.setProxy(seleniumProxy);
        options.setAcceptInsecureCerts(true);

        logger.info("创建带代理的ChromeDriver实例");
        return new ChromeDriver(options);
    }


    /**
     * 创建FirefoxDriver并配置代理
     */
    private WebDriver createFirefoxDriver(Proxy seleniumProxy) {
        FirefoxOptions options = new FirefoxOptions();
        options.addArguments("--ignore-certificate-errors");
        options.addArguments("--ignore-ssl-errors");
        options.setProxy(seleniumProxy);
        options.setAcceptInsecureCerts(true);

        logger.info("创建带代理的FirefoxDriver实例");
        return new FirefoxDriver(options);
    }

    /**
     * 创建EdgeDriver并配置代理
     */
    private WebDriver createEdgeDriver(Proxy seleniumProxy) {
        EdgeOptions options = new EdgeOptions();
        options.addArguments("--ignore-certificate-errors");
        options.addArguments("--ignore-ssl-errors");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-dev-shm-usage");
        options.setProxy(seleniumProxy);
        options.setAcceptInsecureCerts(true);

        logger.info("创建带代理的EdgeDriver实例");
        return new EdgeDriver(options);
    }

    /**
     * 清除捕获的请求
     */
    public void clearCapturedRequests() {
        if (isServiceAvailable()) {
            proxy.newHar();
            logger.info("已清除捕获的请求");
        }
    }

    /**
     * 获取代理端口
     */
    public int getProxyPort() {
        return isServiceAvailable() ? proxy.getPort() : -1;
    }
}
